% gossipMin.erl
%
% Handles computing global min using gossip
%
-module(gossipMin).
-export([start/3]).

% start function used to do gossip
start(Id, Neighbors, MyMin) ->
	random:seed(now()),
	% iterates for number of steps
	TotalIter = ceiling(math:log(length(Neighbors)))+10,
	Smin = gMinFunction_helper(Id, MyMin, Neighbors, 0, TotalIter),
	io:format("~p's new min: ~p~n", [Id, Smin]).

% main gossip loop, at each step it sends its own min to one of its neighbor for comparison
gMinFunction_helper(Id, MyMin, Neighbors, Created, TotalIter) when TotalIter+1 == Created ->
	MyMin;
gMinFunction_helper(Id, MyMin, Neighbors, Created, TotalIter) ->
	case gossipprob:getGossipNode(Neighbors) of
	  {ok, Node} ->
			%io:format("Talking to node ~p~n", [Node]),
			Node ! {gmincomp, MyMin, self()};
		{error, _Msg} -> ok
			%io:format("Talking to myself~n")
	end,
	gMinFunction_helper(Id, processQueue(MyMin), Neighbors, Created+1, TotalIter).

% listens for messages from other nodes so it can update its own
processQueue(MyMin) ->
	receive
		Float when is_float(Float) ->
			if
				Float < MyMin ->
					Smin = Float;
				true ->
					Smin = MyMin
			end,
			processQueue(Smin)
	after
		1000 -> MyMin
	end.

% floor and ceiling functions
floor(X) ->
    T = erlang:trunc(X),
    case (X - T) of
        Neg when Neg < 0 -> T - 1;
        Pos when Pos > 0 -> T;
        _ -> T
    end.

ceiling(X) ->
    T = erlang:trunc(X),
    case (X - T) of
        Neg when Neg < 0 -> T;
        Pos when Pos > 0 -> T + 1;
        _ -> T
    end.
